#ifndef COMPOSANTCOULEUR_H
#define COMPOSANTCOULEUR_H

#include <iostream>

/**
 * Classe qui implémente la composante d'une couleur: il s'agit d'un
 * nombre entier, borné par 0 et 255 (ou 0 et 65535). L'utilité de
 * définir une classe est que les opérations d'addition et
 * soustraction doivent saturer lorsqu'une borne est atteinte, ce qui
 * n'est pas possible avce l'utilisation d'un type élémentaire comme
 * unsigned char et unsigned short.
 *
 * Le nombre de byte utilisé définit la plage sur laquelle les valeurs
 * de la composante sont valides.
 *
 * @author Johan "Solo" Luisier
 * @date Février 2012
 */
class ComposantCouleur
{
public:
  ComposantCouleur( const int& entier = 0 );
  ComposantCouleur( const ComposantCouleur& autre );
  virtual ~ComposantCouleur();
  operator unsigned() const;
  operator int() const;
  operator double() const;
  operator unsigned char() const;
  bool operator==( const ComposantCouleur& autre ) const;
  bool operator<=( const ComposantCouleur& autre ) const;
  bool operator>=( const ComposantCouleur& autre ) const;
  bool operator<( const ComposantCouleur& autre ) const;
  bool operator>( const ComposantCouleur& autre ) const;
  ComposantCouleur& operator=( const ComposantCouleur& autre );
  ComposantCouleur& operator+=( const ComposantCouleur& autre );
  ComposantCouleur& operator-=( const ComposantCouleur& autre );
  ComposantCouleur operator+( const ComposantCouleur& autre ) const;
  ComposantCouleur operator-( const ComposantCouleur& autre ) const;
  // template< typename T >
  // ComposantCouleur& operator*=( const T& scalaire );
  ComposantCouleur& operator*=( const double& scalaire );
  ComposantCouleur& operator=( const int& entier );
  /**
   * Permet d'afficher simplement la valeur de la composante.
   *
   * @param[in] os flot de sortie dans lequel on veut écrire la valeur
   * de la composante.
   * @param[in] comp instance de ComposantCouleur que l'on veut
   * écrire.
   *
   * @return une référence sur l'objet \c os, une fois modifié.
   */
  friend std::ostream& operator<<( std::ostream& os,
				   const ComposantCouleur& comp );
  static const int& maxComposante();
  static const unsigned& nbrBytes();
private:
  /**
   * Valeur de la composante. Chaque opération pouvant la modifier est
   * responsable de vérifier que la valeur finale est bien comprise
   * entre 0 et MaxComposante.
   */
  int Valeur;
  /**
   * Nombre de bytes sur lequel la composante sera écrite /
   * lue. Changer cette valeur permet de changer la qualité des images
   * créées.
   */
  static const unsigned NbrBytes;
  /**
   * Valeur maximale de la composante, est calculée automatiquement à
   * partir de NbrBytes.
   */
  static int MaxComposante;
};



// template< typename T >
// ComposantCouleur& ComposantCouleur::operator*=( const T& scalaire )
// {
//   T tmp( Valeur );
//   tmp *= scalaire;
//   Valeur = static_cast< int >( tmp );

//   Valeur = borne( Valeur, 0, static_cast< int >( maxComposante() ) );

//   return *this;
// }

// template<>
// ComposantCouleur& ComposantCouleur::operator*=( const int& scalaire )
// {
//   Valeur *= scalaire;

//   Valeur = borne( Valeur, 0, static_cast< int >( maxComposante() ) );

//   return *this;
// }

#endif // COMPOSANTCOULEUR_H
